package co.com.desarrollo.pedidos.services.impl;

import java.sql.Timestamp;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import co.com.desarrollo.pedidos.dao.DetallePedidoUsuarioDAO;
import co.com.desarrollo.pedidos.dao.PedidoGrupoDAO;
import co.com.desarrollo.pedidos.dao.PedidoUsuarioDAO;
import co.com.desarrollo.pedidos.entities.DetallePedidoUsuario;
import co.com.desarrollo.pedidos.entities.EstadoPedido;
import co.com.desarrollo.pedidos.entities.PedidoGrupo;
import co.com.desarrollo.pedidos.entities.PedidoUsuario;
import co.com.desarrollo.pedidos.entities.Producto;
import co.com.desarrollo.pedidos.entities.Tienda;
import co.com.desarrollo.pedidos.entities.Usuario;
import co.com.desarrollo.pedidos.services.GeneralService;
import co.com.desarrollo.pedidos.services.PedidoService;
import co.com.desarrollo.pedidos.services.ProductoService;
import co.com.desarrollo.pedidos.services.TiendaService;
import co.com.desarrollo.pedidos.services.UsuarioService;
import co.com.desarrollo.pedidos.services.exceptions.DetallePedidoNotFoundException;
import co.com.desarrollo.pedidos.services.exceptions.EstadoPedidoNotFoundException;
import co.com.desarrollo.pedidos.services.exceptions.IllegalEstadoPedidoException;
import co.com.desarrollo.pedidos.services.exceptions.PedidoGrupoNotFoundException;
import co.com.desarrollo.pedidos.services.exceptions.PedidoUsuarioNotFoundException;
import co.com.desarrollo.pedidos.services.exceptions.ProductoNotFoundException;
import co.com.desarrollo.pedidos.services.exceptions.TiendaNotFoundException;
import co.com.desarrollo.pedidos.services.exceptions.UsuarioNotFoundException;

@Service("pedidoService")
public class PedidoServiceImpl implements PedidoService {

	@Autowired
	private PedidoGrupoDAO pedidoGrupoDAO;
	@Autowired
	private PedidoUsuarioDAO pedidoUsuarioDAO;
	@Autowired
	private DetallePedidoUsuarioDAO detallePedidoUsuarioDAO;
	@Autowired
	private TiendaService tiendaService;
	@Autowired
	private GeneralService generalService;
	@Autowired
	private UsuarioService usuarioService;
	@Autowired
	private ProductoService productoService;

	@Override
	public DetallePedidoUsuario addDetallePedido(DetallePedidoUsuario detallePedidoUsuario, PedidoUsuario pedidoUsuario) throws IllegalEstadoPedidoException, TiendaNotFoundException, UsuarioNotFoundException, DetallePedidoNotFoundException, PedidoGrupoNotFoundException, PedidoUsuarioNotFoundException {
		pedidoUsuario = findPedidoUsuarioMethods(pedidoUsuario);
		if(pedidoUsuario.getPedidoGrupo().getEstadoPedido().getIdestadoPedido() == 0)
		{			 
			detallePedidoUsuario.setPedidoUsuario(pedidoUsuario);
			return detallePedidoUsuarioDAO.store(detallePedidoUsuario);
		}
		else
			throw new IllegalEstadoPedidoException("El pedido no se encuentra en estado inicial.");
	}

	@Override
	public PedidoGrupo cancelarPedidoGrupo(PedidoGrupo pedidoGrupo) throws IllegalEstadoPedidoException, DetallePedidoNotFoundException, TiendaNotFoundException, PedidoGrupoNotFoundException {
		pedidoGrupo = findPedidoGrupoMethods(pedidoGrupo);
		if (pedidoGrupo.getEstadoPedido().getIdestadoPedido() == 0) {
			EstadoPedido estadoPedido = new EstadoPedido();
			estadoPedido.setIdestadoPedido(3);
			pedidoGrupo.setEstadoPedido(generalService.getEstadoPedidoById(estadoPedido));
			return pedidoGrupoDAO.store(pedidoGrupo);
		}
		else
			throw new IllegalEstadoPedidoException("El pedido no se encuentra en estado inicial.");
	}

	@Override
	public PedidoGrupo confirmarPedidoGrupo(PedidoGrupo pedidoGrupo) throws IllegalEstadoPedidoException, DetallePedidoNotFoundException, TiendaNotFoundException, PedidoGrupoNotFoundException {
		pedidoGrupo = findPedidoGrupoMethods(pedidoGrupo);
		if (pedidoGrupo.getEstadoPedido().getIdestadoPedido() == 1) {
			EstadoPedido estadoPedido = new EstadoPedido();
			estadoPedido.setIdestadoPedido(2);
			pedidoGrupo.setEstadoPedido(generalService.getEstadoPedidoById(estadoPedido));
			Date date = new Date();
			pedidoGrupo.setFechaEntrega(new Timestamp(date.getTime()));
			return pedidoGrupoDAO.store(pedidoGrupo);
		}
		else
			throw new IllegalEstadoPedidoException("El pedido no se encuentra en estado solicitado.");
	}

	@Override
	public List<DetallePedidoUsuario> getAllDetallePedidosUsuario() {
		return detallePedidoUsuarioDAO.findAll();
	}

	@Override
	public List<PedidoGrupo> getAllPedidosGrupo() {
		return pedidoGrupoDAO.findAll();
	}

	@Override
	public List<PedidoUsuario> getAllPedidosUsuario() {
		return pedidoUsuarioDAO.findAll();
	}

	@Override
	public DetallePedidoUsuario getDetallePedidoById(
			DetallePedidoUsuario detallePedidoUsuario) {
		return detallePedidoUsuarioDAO.findById(detallePedidoUsuario.getIddetallePedido());
	}

	@Override
	public List<DetallePedidoUsuario> getDetallePedidoByPedidoUsuario(
			PedidoUsuario pedidoUsuario) throws TiendaNotFoundException, UsuarioNotFoundException, DetallePedidoNotFoundException, PedidoGrupoNotFoundException, PedidoUsuarioNotFoundException {
		return detallePedidoUsuarioDAO.findByPedidoUsuario(findPedidoUsuarioMethods(pedidoUsuario).getIdpedidoUsuario());
	}
	
	@Override
	public DetallePedidoUsuario getDetallePedidoByPedidoUsuarioProducto(PedidoUsuario pedidoUsuario, Producto producto) throws ProductoNotFoundException, TiendaNotFoundException, UsuarioNotFoundException, DetallePedidoNotFoundException, PedidoGrupoNotFoundException, PedidoUsuarioNotFoundException {
		return detallePedidoUsuarioDAO.findByPedidoUsuarioProducto(findPedidoUsuarioMethods(pedidoUsuario).getIdpedidoUsuario(),productoService.findProductoBothMethods(producto).getIdproducto());
	}

	@Override
	public PedidoGrupo getPedidoGrupoById(PedidoGrupo pedidoGrupo) {
		return pedidoGrupoDAO.findById(pedidoGrupo.getIdpedidoGrupo());
	}

	@Override
	public PedidoUsuario getPedidoUsuarioById(PedidoUsuario pedidoUsuario) {
		return pedidoUsuarioDAO.findById(pedidoUsuario.getIdpedidoUsuario());
	}

	@Override
	public List<PedidoUsuario> getPedidosUsuarioByUsuarioPedidoGrupo(
			Usuario usuario, PedidoGrupo pedidoGrupo) throws UsuarioNotFoundException, DetallePedidoNotFoundException, TiendaNotFoundException, PedidoGrupoNotFoundException {
		return pedidoUsuarioDAO.findByUsuarioPedidoGrupo(usuarioService.findUsuarioMethods(usuario).getIdusuario(), findPedidoGrupoMethods(pedidoGrupo).getIdpedidoGrupo());
	}
	
	@Override
	public PedidoUsuario getPedidoUsuarioActivoByUsuarioPedidoGrupo(
			Usuario usuario, PedidoGrupo pedidoGrupo) throws UsuarioNotFoundException, DetallePedidoNotFoundException, TiendaNotFoundException, PedidoGrupoNotFoundException {
		return pedidoUsuarioDAO.findActivoByUsuarioPedidoGrupo(usuarioService.findUsuarioMethods(usuario).getIdusuario(), findPedidoGrupoMethods(pedidoGrupo).getIdpedidoGrupo());
	}

	@Override
	public List<PedidoGrupo> getPedidosGrupoByEstadoPedido(
			EstadoPedido estadoPedido) throws EstadoPedidoNotFoundException {
		return pedidoGrupoDAO.findPedidosGrupoByEstadoPedido(generalService.findEstadoPedidoMethods(estadoPedido).getIdestadoPedido());
	}

	@Override
	public List<PedidoUsuario> getPedidosUsuarioByPedidoGrupo(
			PedidoGrupo pedidoGrupo) throws DetallePedidoNotFoundException, TiendaNotFoundException, PedidoGrupoNotFoundException {
		return pedidoUsuarioDAO.findPedidosUsuarioByPedidoGrupo(findPedidoGrupoMethods(pedidoGrupo).getIdpedidoGrupo());
	}

	@Override
	public PedidoGrupo realizarPedidoGrupo(PedidoGrupo pedidoGrupo, Usuario usuario) throws IllegalEstadoPedidoException, UsuarioNotFoundException, DetallePedidoNotFoundException, TiendaNotFoundException, PedidoGrupoNotFoundException {
		pedidoGrupo = getPedidoUsuarioActivoByUsuarioPedidoGrupo(usuario, pedidoGrupo).getPedidoGrupo();
		if (pedidoGrupo.getEstadoPedido().getIdestadoPedido() == 0) {
			EstadoPedido estadoPedido = new EstadoPedido();
			estadoPedido.setIdestadoPedido(1);
			pedidoGrupo.setEstadoPedido(generalService.getEstadoPedidoById(estadoPedido));
			pedidoGrupo.setUsuario(usuario);
			Date date = new Date();
			pedidoGrupo.setFechaPedido(new Timestamp(date.getTime()));
			return pedidoGrupoDAO.store(pedidoGrupo);
		}
		else
			throw new IllegalEstadoPedidoException("El pedido no se encuentra en estado inicial.");
	}

	@Override
	public void removeDetallePedido(DetallePedidoUsuario detallePedidoUsuario) throws IllegalEstadoPedidoException, TiendaNotFoundException, UsuarioNotFoundException, DetallePedidoNotFoundException, PedidoGrupoNotFoundException, PedidoUsuarioNotFoundException, ProductoNotFoundException {
		detallePedidoUsuario = findDetallePedidoUsuarioMethods(detallePedidoUsuario);
		if(detallePedidoUsuario.getPedidoUsuario().getPedidoGrupo().getEstadoPedido().getIdestadoPedido() == 0)
		{
			detallePedidoUsuarioDAO.delete(detallePedidoUsuario.getIddetallePedido());
		}
		else
			throw new IllegalEstadoPedidoException("El pedido no se encuentra en estado inicial.");

	}

	@Override
	public void removePedidoUsuario(PedidoUsuario pedidoUsuario) throws IllegalEstadoPedidoException, TiendaNotFoundException, UsuarioNotFoundException, DetallePedidoNotFoundException, PedidoGrupoNotFoundException, PedidoUsuarioNotFoundException {
		pedidoUsuario = findPedidoUsuarioMethods(pedidoUsuario);
		if(pedidoUsuario.getPedidoGrupo().getEstadoPedido().getIdestadoPedido() == 0)
		{
			pedidoUsuarioDAO.delete(pedidoUsuario.getIdpedidoUsuario());
		}
		else
			throw new IllegalEstadoPedidoException("El pedido no se encuentra en estado inicial.");
	}

	@Override
	public PedidoUsuario setPedidoUsuario(Usuario usuario, Tienda tienda) throws TiendaNotFoundException, UsuarioNotFoundException, DetallePedidoNotFoundException, PedidoGrupoNotFoundException {
		
		PedidoGrupo pedidoGrupo = getPedidoGrupoByEstadoEsperaTienda(tienda);
		if (pedidoGrupo == null) {
			pedidoGrupo = new PedidoGrupo();
			pedidoGrupo.setTienda(tiendaService.findTiendaBothMethods(tienda));
			EstadoPedido estadoPedido = new EstadoPedido();
			estadoPedido.setIdestadoPedido(0);
			pedidoGrupo.setEstadoPedido(generalService.getEstadoPedidoById(estadoPedido));
			pedidoGrupo = setPedidoGrupo(pedidoGrupo);
		}
		
		PedidoUsuario pedidoUsuario = getPedidoUsuarioActivoByUsuarioPedidoGrupo(usuario, pedidoGrupo);
		if (pedidoUsuario == null) {
			pedidoUsuario = new PedidoUsuario(usuarioService.findUsuarioMethods(usuario));
			pedidoUsuario.setPedidoGrupo(pedidoGrupo);
			Date date = new Date();
			pedidoUsuario.setFechaPedido(new Timestamp(date.getTime()));
			return pedidoUsuarioDAO.store(pedidoUsuario);
		}
		else
			return pedidoUsuario;
	}
	
	@Override
	public PedidoGrupo setPedidoGrupo(PedidoGrupo pedidoGrupo) {
		PedidoGrupo a = pedidoGrupoDAO.store(pedidoGrupo) ;
		return a;
	}

	@Override
	public List<PedidoUsuario> getPedidosUsuarioByUsuario(
			Usuario usuario) {
		return pedidoUsuarioDAO.findPedidosUsuarioByUsuario(usuario.getIdusuario());
	}	

	@Override
	public PedidoUsuario getPedidoUsuarioByTienda(Usuario usuario, Tienda tienda) throws TiendaNotFoundException, UsuarioNotFoundException, DetallePedidoNotFoundException, PedidoGrupoNotFoundException {
		PedidoGrupo pedidoGrupo = getPedidoGrupoByEstadoEsperaTienda(tienda);
		if (pedidoGrupo != null) {
			PedidoUsuario pedidoUsuario = getPedidoUsuarioActivoByUsuarioPedidoGrupo(usuario, pedidoGrupo);
			if (pedidoUsuario != null) {
				return pedidoUsuario;
			}
		}
		return null;
	}

	
	@Override
	public DetallePedidoUsuario findDetallePedidoUsuarioMethods (
			DetallePedidoUsuario detallePedidoUsuario) throws TiendaNotFoundException, UsuarioNotFoundException, DetallePedidoNotFoundException, PedidoGrupoNotFoundException, PedidoUsuarioNotFoundException, ProductoNotFoundException {
		DetallePedidoUsuario detallePedidoUsuarioFound = getDetallePedidoById(detallePedidoUsuario);
		if (detallePedidoUsuarioFound == null){
			detallePedidoUsuario = getDetallePedidoByPedidoUsuarioProducto(detallePedidoUsuario.getPedidoUsuario(), detallePedidoUsuario.getProducto());
		}
		else
			detallePedidoUsuario = detallePedidoUsuarioFound;
		if (detallePedidoUsuario != null)
			return detallePedidoUsuario;
		throw new DetallePedidoNotFoundException("El detalle pedido solicitado no existe.");
	}

	@Override
	public PedidoGrupo findPedidoGrupoMethods(PedidoGrupo pedidoGrupo) throws DetallePedidoNotFoundException, TiendaNotFoundException, PedidoGrupoNotFoundException {
		PedidoGrupo pedidoGrupoFound = getPedidoGrupoById(pedidoGrupo);
		if (pedidoGrupoFound == null)
			pedidoGrupoFound = getPedidoGrupoByEstadoEsperaTienda(tiendaService.findTiendaBothMethods(pedidoGrupo.getTienda()));
		else
			pedidoGrupo = pedidoGrupoFound;
		if (pedidoGrupo!=null)
			return pedidoGrupo;
		throw new PedidoGrupoNotFoundException("El pedido grupo solicitado no existe.");
	}

	@Override
	public PedidoUsuario findPedidoUsuarioMethods(PedidoUsuario pedidoUsuario) throws TiendaNotFoundException, UsuarioNotFoundException, DetallePedidoNotFoundException, PedidoGrupoNotFoundException, PedidoUsuarioNotFoundException {
		PedidoUsuario pedidoUsuarioFound = getPedidoUsuarioById(pedidoUsuario);
		if (pedidoUsuarioFound == null){
			pedidoUsuarioFound = pedidoUsuario; 
			pedidoUsuario = getPedidoUsuarioActivoByUsuarioPedidoGrupo(
					usuarioService.findUsuarioMethods(pedidoUsuario.getUsuario()),
					findPedidoGrupoMethods(pedidoUsuario.getPedidoGrupo()));
			if (pedidoUsuario == null) {
				pedidoUsuario = getPedidoUsuarioByTienda(usuarioService.findUsuarioMethods(pedidoUsuarioFound.getUsuario()),
						findPedidoGrupoMethods(pedidoUsuarioFound.getPedidoGrupo()).getTienda());
			}
		}
		else
			pedidoUsuario = pedidoUsuarioFound;
		if (pedidoUsuario != null)
			return pedidoUsuario;
		throw new PedidoUsuarioNotFoundException("El pedido usuario solicitado no existe.");
	}

	@Override
	public PedidoGrupo getPedidoGrupoByEstadoEsperaTienda(Tienda tienda)throws TiendaNotFoundException {
		return pedidoGrupoDAO.findByStatusTienda(0, tiendaService.findTiendaBothMethods(tienda).getIdtienda());
	}
	
	@Override
	public PedidoGrupo getPedidoGrupoByEstadoCanceladoTienda(Tienda tienda)
			throws TiendaNotFoundException {
		return pedidoGrupoDAO.findByStatusTienda(3, tiendaService.findTiendaBothMethods(tienda).getIdtienda());
	}

	@Override
	public PedidoGrupo getPedidoGrupoByEstadoEntregadoTienda(Tienda tienda)
			throws TiendaNotFoundException {
		return pedidoGrupoDAO.findByStatusTienda(2, tiendaService.findTiendaBothMethods(tienda).getIdtienda());
	}

	@Override
	public PedidoGrupo getPedidoGrupoByEstadoSolicitadoTienda(Tienda tienda)
			throws TiendaNotFoundException {
		return pedidoGrupoDAO.findByStatusTienda(1, tiendaService.findTiendaBothMethods(tienda).getIdtienda());
	}
	
}
